#include "stdafx.h"
#include "RenderingParams.h"

namespace Cvekas {

void RenderingParams::setPerFrame(float time)
{
	this->time = time;
}

void RenderingParams::setPerScene(const Matrix& projection, const Vector2& rt_size, bool perspective)
{
	this->projection = projection;

	this->rendertarget_size = rt_size;

	view_projection = view * projection;
	world_view_projection = world_view * projection;

	if(perspective)
	{
		// Z near/far derivation from perspective LH projection matrix:
		// a = m33 = zf/(zf-zn)
		// b = m43 = (-zn*zf)/(zf-zn) (see D3DXMatrixPerspectiveFovLH docs)
		//
		// zn:
		// b / a = ((-zn*zf)/(zf-zn)) / (zf/(zf-zn)) = -zn
		// zn = -b / a
		//
		// zf:
		// a = zf/(zf-zn) 
		// a/zf = 1/(zf-zn) 
		// zf/a = zf - zn
		// zn = zf - (zf/za)
		// zn / zf = 1 - (1/a)
		// 1 / zf = (1 - 1/a) / zn
		// zf = zn / (1 - 1/a)

		float a = projection._33;
		float b = projection._34;

		clip_near = -b / a;
		clip_far = clip_near / (1.0f - 1.0f / a);

		// fov derivation from perspective LH projection:
		// a = m22 = ctg(fov/2) (see D3DXMatrixPerspectiveFovLH docs)
		// fov = 2 * arcctg(a)
		// fov = 2 * arctan(1/a)
		projection_fov = 2.0f * atan(1.0f / projection._22);
	}
	else
	{
		// Z near/far derivation from orthographic LH projection matrix:
		// a = m33 = 1/(zf-zn)
		// b = m43 = -zn/(zf-zn) (see D3DXMatrixOrthoLH docs)
		//
		// zn:
		// b / a = (-zn/(zf-zn)) / (1/(zf-zn)) = -zn
		// zn = -b / a
		//
		// zf:
		// a = 1/(zf-zn) 
		// 1/a = zf - zn 
		// zf = 1/a + zn

		float a = projection._33;
		float b = projection._34;

		clip_near = -b / a;
		clip_far = 1.0f / a + clip_near;

		// No fov for orthographic projection!
		projection_fov = 0.0f;
	}
}

void RenderingParams::setPerBatch(const Matrix& world, int pass)
{
	this->world = world;

	world_view = world * view;
	world_view_projection = world * view_projection;

	this->pass = pass;
}

void RenderingParams::setCamera(const Camera& camera)
{
	view = camera.getViewMatrix();

	world_view = world * view;
	view_projection = view * projection;
	world_view_projection = world * view_projection;

	camera_pos = camera.getPosition();
	camera_dir = camera.getDirection();
	camera_up = camera.getUp();
}

} // namespace